#include "connection.h"
#include "netparam.h"
Connection::Connection(QObject *parent):QTcpSocket(parent),hasError(false)
{
    curDataNeedLen = -1;
    connect(this,SIGNAL(readyRead()),SLOT(onReadyRead()),Qt::QueuedConnection);// avoid to process a message too long
    connect(this,SIGNAL(disconnected()),SLOT(deleteLater()));
    connect(this,SIGNAL(error(QAbstractSocket::SocketError)),SLOT(onError(QAbstractSocket::SocketError)));

    // log information
    connect(this,SIGNAL(connected()),SLOT(onConnected()));
    connect(this,SIGNAL(disconnected()),SLOT(onDisconnected()));
    connect(this,SIGNAL(bytesWritten(qint64)),SLOT(onBytesWritten(qint64)));
}
void Connection::onReadyRead()
{
    if(curDataNeedLen==-1 && !getDataNeedLen())
        return;
    while(bytesAvailable() && dataReadBuffer.length()<curDataNeedLen)
        dataReadBuffer.append(read(curDataNeedLen));
    if(dataReadBuffer.length()==curDataNeedLen)
    {
        qDebug("in connection,get data from %s",ipTo.toAscii().data());
        emit recieveData(ipTo,dataReadBuffer);
        dataReadBuffer.clear();// QByteArray,automatic copy on write,is this right?
        curDataNeedLen=-1;
        if(bytesAvailable()) emit readyRead();
    }
}

void Connection::onSendData(QByteArray data)
{
    if(data.isEmpty())
        return;
    unsigned int n = data.length();
    write(QByteArray::number(n).append(' '));
    write(data);
}
int Connection::getDataNeedLen()
{
    if(curDataNeedLen!=-1) return curDataNeedLen;
    while(bytesAvailable() && !dataReadBuffer.endsWith(' '))
        dataReadBuffer.append(read(1));
    if(!dataReadBuffer.endsWith(' '))
        return 0;
    dataReadBuffer.chop(1);
    curDataNeedLen=dataReadBuffer.toUInt();
    dataReadBuffer.clear();
    return curDataNeedLen;

}

void Connection::onError(QAbstractSocket::SocketError errorCode)
{
    emit notify(ipTo,NetError::NetworkError);// other errors
    hasError = true;
}


// override connectToHost,for remembering the ip
bool Connection::tryConnect(const QString &hostName, quint16 port, OpenMode mode)
{
   ipTo = hostName;
   QTcpSocket::connectToHost(hostName,port,mode);// when error emitted,kill self
   return !hasError;
}
void Connection::onConnected()
{
    qDebug("connect to %s sucessfully",ipTo.toAscii().data());
}
void Connection::onDisconnected()
{
    qDebug("%s disconnect",ipTo.toAscii().data());
}
// here to record the data written,for dbugging use
void Connection::onBytesWritten(qint64 len)
{
    qDebug()<<"bytes written to network,length "<<len<<",in "<<ipTo;
}
